# -*-coding:utf-8-*-
import os
import sys


# 默认参数
def fun(a, b=1):
    print(a, b)
fun(1, 2)
fun(1, b=2)

# 定义默认参数要牢记一点：默认参数必须指向不变对象
# 以下这个函数如果被多次调用会在默认添加多个END字符串
def add1(a=[]):
    a.append('END')
    return a

# 为了避免这个问题，应该把传入的默认参数设置为不可变的
def add2(a=None):
    a = []
    a.append('END')
    return a


# 可变参数
def fun1(*args):
    print(args)
xx = (1, 2, 3)
fun1(*xx)
fun1(3, 4, 5)


# 关键字参数
def fun2(**args):
    print(args)
yy = {'a': 1, 'b': 2}
fun2(**yy)
fun2(a=1, b=2)


# 命名关键字参数,和普通关键字参数不同,命名关键字参数需要一个用来区分的分隔符*,它后面的参数被认为是命名关键字参数
def fun3(a, *, b, c):
    print(a, b, c)
fun3(1, b=3, c=4)

def fun4(a, *, b=2, c=3):
    print(a, b, c)
fun4(1)

# 不过也有例外,如果参数中已经有一个可变参数的话,前面讲的星号分割符就不要写了,参数中只允许有一个*号
def fun5(a, *b, c):
    print(a, b, c)
fun5(1, 2, 3, c=4)
fun5(a=1, c=2)


# 组合参数,这些参数在书写时要遵循一定的顺序即：位置参数、默认参数、变长参数、命名关键字参数、关键字参数
def fun6(arg, default=2):
    print(arg, default)
def fun7(*args, default=2):
    print(args, default)
def fun8(arg, *args, namekwargs, **kwargs):
    print(arg, args, namekwargs, kwargs)

fun8(1, 2, 3, namekwargs=4, a=5, b=6)


# 函数作为参数
def foo(func, *args, **kwargs):
    print(func.__name__)
    return func(*args, **kwargs)
def add(a, b, c, d):
    return a+b+c+d
print(foo(add, 1, 2, c=3, d=4))


# 函数间接调用
def make(label):
    def echo(name):
        print(label, ":", name)
    return echo
e = make('hello')
e('jack')